home *** CD-ROM | disk | FTP | other *** search
Text File | 2008-08-20 | 34.4 KB | 1,039 lines |
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla XML-RPC Client component.
- *
- * The Initial Developer of the Original Code is
- * Digital Creations 2, Inc.
- * Portions created by the Initial Developer are Copyright (C) 2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Martijn Pieters <mj@digicool.com> (original author)
- * Samuel Sieb <samuel@sieb.net>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
- /*
- * nsXmlRpcClient XPCOM component
- * Version: $Revision: 1.39 $
- *
- * $Id: nsXmlRpcClient.js,v 1.39 2006/10/24 16:02:01 silver%warwickcompsoc.co.uk Exp $
- */
-
- /*
- * Constants
- */
- const XMLRPCCLIENT_CONTRACTID = '@mozilla.org/xml-rpc/client;1';
- const XMLRPCCLIENT_CID =
- Components.ID('{4d7d15c0-3747-4f7f-b6b3-792a5ea1a9aa}');
- const XMLRPCCLIENT_IID = Components.interfaces.nsIXmlRpcClient;
-
- const XMLRPCFAULT_CONTRACTID = '@mozilla.org/xml-rpc/fault;1';
- const XMLRPCFAULT_CID =
- Components.ID('{691cb864-0a7e-448c-98ee-4a7f359cf145}');
- const XMLRPCFAULT_IID = Components.interfaces.nsIXmlRpcFault;
-
- const XMLHTTPREQUEST_CONTRACTID = '@mozilla.org/xmlextras/xmlhttprequest;1';
-
- const NSICHANNEL = Components.interfaces.nsIChannel;
-
- const DEBUG = false;
- const DEBUGPARSE = false;
-
- const DOMNode = Components.interfaces.nsIDOMNode;
- /*
- * Class definitions
- */
-
- /* The nsXmlRpcFault class constructor. */
- function nsXmlRpcFault() {}
-
- /* the nsXmlRpcFault class def */
- nsXmlRpcFault.prototype = {
- faultCode: 0,
- faultString: '',
-
- init: function(faultCode, faultString) {
- this.faultCode = faultCode;
- this.faultString = faultString;
- },
-
- toString: function() {
- return '<XML-RPC Fault: (' + this.faultCode + ') ' +
- this.faultString + '>';
- },
-
- // nsISupports interface
- QueryInterface: function(iid) {
- if (!iid.equals(Components.interfaces.nsISupports) &&
- !iid.equals(XMLRPCFAULT_IID))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- return this;
- }
- };
-
- /* The nsXmlRpcClient class constructor. */
- function nsXmlRpcClient() {}
-
- /* the nsXmlRpcClient class def */
- nsXmlRpcClient.prototype = {
- _serverUrl: null,
- _useAuth: false,
-
- init: function(serverURL) {
- this._serverUrl = serverURL;
- this._encoding = "UTF-8";
- },
-
- setAuthentication: function(username, password){
- if ((typeof username == "string") &&
- (typeof password == "string")){
- this._useAuth = true;
- this._username = username;
- this._password = password;
- }
- },
-
- clearAuthentication: function(){
- this._useAuth = false;
- },
-
- setEncoding: function(encoding){
- this._encoding = encoding;
- },
-
- get serverUrl() { return this._serverUrl; },
-
- // Internal copy of the status
- _status: null,
- _listener: null,
-
- asyncCall: function(listener, context, methodName, methodArgs, count) {
- debug('asyncCall');
- // Check for call in progress.
- if (this._inProgress)
- throw Components.Exception('Call in progress!');
-
- // Check for the server URL;
- if (!this._serverUrl)
- throw Components.Exception('Not initialized');
-
- this._inProgress = true;
-
- // Clear state.
- this._foundFault = false;
- this._passwordTried = false;
- this._result = null;
- this._fault = null;
- this._status = null;
- this._responseStatus = null;
- this._responseString = null;
- this._listener = listener;
- this._seenStart = false;
- this._context = context;
-
- debug('Arguments: ' + methodArgs);
-
- // Generate request body
- var xmlWriter = new XMLWriter(this._encoding);
- this._generateRequestBody(xmlWriter, methodName, methodArgs);
-
- var requestBody = xmlWriter.data;
-
- debug('Request: ' + requestBody);
-
- this.xmlhttp = Components.classes[XMLHTTPREQUEST_CONTRACTID]
- .createInstance(Components.interfaces.nsIXMLHttpRequest);
- if (this._useAuth) {
- this.xmlhttp.open('POST', this._serverUrl, true,
- this._username, this._password);
- } else {
- this.xmlhttp.open('POST', this._serverUrl);
- }
- this.xmlhttp.onload = this._onload;
- this.xmlhttp.onerror = this._onerror;
- this.xmlhttp.parent = this;
- this.xmlhttp.setRequestHeader('Content-Type','text/xml');
- this.xmlhttp.send(requestBody);
- var chan = this.xmlhttp.channel.QueryInterface(NSICHANNEL);
- chan.notificationCallbacks = this;
- },
-
- _onload: function(e) {
- var result;
- var parent = e.target.parent;
- parent._inProgress = false;
- parent._responseStatus = e.target.status;
- parent._responseString = e.target.statusText;
- if (!e.target.responseXML) {
- if (e.target.status) {
- try {
- parent._listener.onError(parent, parent._context,
- Components.results.NS_ERROR_FAILURE,
- 'Server returned status ' + e.target.status);
- } catch (ex) {
- debug('Exception in listener.onError: ' + ex);
- }
- } else {
- try {
- parent._listener.onError(parent, parent._context,
- Components.results.NS_ERROR_FAILURE,
- 'Unknown network error');
- } catch (ex) {
- debug('Exception in listener.onError: ' + ex);
- }
- }
- return;
- }
- try {
- e.target.responseXML.normalize();
- result = parent.parse(e.target.responseXML);
- } catch (ex) {
- try {
- parent._listener.onError(parent, parent._context,
- ex.result, ex.message);
- } catch (ex) {
- debug('Exception in listener.onError: ' + ex);
- }
- return;
- }
- if (parent._foundFault) {
- parent._fault = result;
- try {
- parent._listener.onFault(parent, parent._context, result);
- } catch(ex) {
- debug('Exception in listener.onFault: ' + ex);
- }
- } else {
- parent._result = result.value;
- try {
- parent._listener.onResult(parent, parent._context,
- result.value);
- } catch (ex) {
- debug('Exception in listener.onResult: ' + ex);
- }
- }
- },
-
- _onerror: function(e) {
- var parent = e.target.parent;
- parent._inProgress = false;
- try {
- parent._listener.onError(parent, parent._context,
- Components.results.NS_ERROR_FAILURE,
- 'Unknown network error');
- } catch (ex) {
- debug('Exception in listener.onError: ' + ex);
- }
- },
-
- _foundFault: false,
-
- _fault: null,
- _result: null,
- _responseStatus: null,
- _responseString: null,
-
- get fault() { return this._fault; },
- get result() { return this._result; },
- get responseStatus() { return this._responseStatus; },
- get responseString() { return this._responseString; },
-
- /* Convenience. Create an appropriate XPCOM object for a given type */
- INT: 1,
- BOOLEAN: 2,
- STRING: 3,
- DOUBLE: 4,
- DATETIME: 5,
- ARRAY: 6,
- STRUCT: 7,
- BASE64: 8, // Not part of nsIXmlRpcClient interface, internal use.
- createType: function(type, uuid) {
- const SUPPORTSID = '@mozilla.org/supports-';
- switch(type) {
- case this.INT:
- uuid.value = Components.interfaces.nsISupportsPRInt32
- return createInstance(SUPPORTSID + 'PRInt32;1',
- 'nsISupportsPRInt32');
-
- case this.BOOLEAN:
- uuid.value = Components.interfaces.nsISupportsPRBool
- return createInstance(SUPPORTSID + 'PRBool;1',
- 'nsISupportsPRBool');
-
- case this.STRING:
- uuid.value = Components.interfaces.nsISupportsCString
- return createInstance(SUPPORTSID + 'cstring;1',
- 'nsISupportsCString');
-
- case this.DOUBLE:
- uuid.value = Components.interfaces.nsISupportsDouble
- return createInstance(SUPPORTSID + 'double;1',
- 'nsISupportsDouble');
-
- case this.DATETIME:
- uuid.value = Components.interfaces.nsISupportsPRTime
- return createInstance(SUPPORTSID + 'PRTime;1',
- 'nsISupportsPRTime');
-
- case this.ARRAY:
- uuid.value = Components.interfaces.nsISupportsArray
- return createInstance(SUPPORTSID + 'array;1',
- 'nsISupportsArray');
-
- case this.STRUCT:
- uuid.value = Components.interfaces.nsIDictionary
- return createInstance('@mozilla.org/dictionary;1',
- 'nsIDictionary');
-
- default: throw Components.Exception('Unsupported type');
- }
- },
-
- // nsISupports interface
- QueryInterface: function(iid) {
- if (!iid.equals(Components.interfaces.nsISupports) &&
- !iid.equals(XMLRPCCLIENT_IID) &&
- !iid.equals(Components.interfaces.nsIInterfaceRequestor))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- return this;
- },
-
- // nsIInterfaceRequester interface
- getInterface: function(iid, result){
- if (iid.equals(Components.interfaces.nsIAuthPrompt)){
- return this;
- }
- Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
- return null;
- },
-
- // nsIAuthPrompt interface
- _passwordTried: false,
- promptUsernameAndPassword: function(dialogTitle, text, passwordRealm,
- savePassword, user, pwd){
-
- if (this._useAuth){
- if (this._passwordTried){
- return false;
- }
- user.value = this._username;
- pwd.value = this._password;
- this._passwordTried = true;
- return true;
- }
- return false;
- },
-
- /* Generate the XML-RPC request body */
- _generateRequestBody: function(writer, methodName, methodArgs) {
- writer.startElement('methodCall');
-
- writer.startElement('methodName');
- writer.write(methodName);
- writer.endElement('methodName');
-
- writer.startElement('params');
- for (var i = 0; i < methodArgs.length; i++) {
- writer.startElement('param');
- this._generateArgumentBody(writer, methodArgs[i]);
- writer.endElement('param');
- }
- writer.endElement('params');
-
- writer.endElement('methodCall');
- },
-
- /* Write out a XML-RPC parameter value */
- _generateArgumentBody: function(writer, obj) {
- writer.startElement('value');
- var sType = this._typeOf(obj);
- switch (sType) {
- case 'PRUint8':
- case 'PRUint16':
- case 'PRInt16':
- case 'PRInt32':
- obj=obj.QueryInterface(Components.interfaces['nsISupports' +
- sType]);
- writer.startElement('i4');
- writer.write(obj.toString());
- writer.endElement('i4');
- break;
-
- case 'PRBool':
- obj=obj.QueryInterface(Components.interfaces.nsISupportsPRBool);
- writer.startElement('boolean');
- writer.write(obj.data ? '1' : '0');
- writer.endElement('boolean');
- break;
-
- case 'Char':
- case 'CString':
- obj=obj.QueryInterface(Components.interfaces['nsISupports' +
- sType]);
- writer.startElement('string');
- writer.write(obj.toString());
- writer.endElement('string');
- break;
-
- case 'Float':
- case 'Double':
- obj=obj.QueryInterface(Components.interfaces['nsISupports' +
- sType]);
- writer.startElement('double');
- writer.write(obj.toString());
- writer.endElement('double');
- break;
-
- case 'PRTime':
- obj = obj.QueryInterface(
- Components.interfaces.nsISupportsPRTime);
- var date = new Date(obj.data)
- writer.startElement('dateTime.iso8601');
- writer.write(iso8601Format(date));
- writer.endElement('dateTime.iso8601');
- break;
-
- case 'InputStream':
- obj = obj.QueryInterface(Components.interfaces.nsIInputStream);
- obj = toScriptableStream(obj);
- writer.startElement('base64');
- streamToBase64(obj, writer);
- writer.endElement('base64');
- break;
-
- case 'Array':
- obj = obj.QueryInterface(
- Components.interfaces.nsISupportsArray);
- writer.startElement('array');
- writer.startElement('data');
- for (var i = 0; i < obj.Count(); i++)
- this._generateArgumentBody(writer, obj.GetElementAt(i));
- writer.endElement('data');
- writer.endElement('array');
- break;
-
- case 'Dictionary':
- obj = obj.QueryInterface(Components.interfaces.nsIDictionary);
- writer.startElement('struct');
- var keys = obj.getKeys({});
- for (var k = 0; k < keys.length; k++) {
- writer.startElement('member');
- writer.startElement('name');
- writer.write(keys[k]);
- writer.endElement('name');
- this._generateArgumentBody(writer, obj.getValue(keys[k]));
- writer.endElement('member');
- }
- writer.endElement('struct');
- break;
-
- default:
- throw Components.Exception('Unsupported argument', null, null,
- obj);
- }
-
- writer.endElement('value');
- },
-
- /* Determine type of a nsISupports primitive, array or dictionary. */
- _typeOf: function(obj) {
- // XPConnect alows JS to pass in anything, because we are a regular
- // JS object to it. So we have to test rigorously.
- if (typeof obj != 'object') return 'Unknown';
-
- // Anything else not nsISupports is not allowed.
- if (typeof obj.QueryInterface != 'function') return 'Unknown';
-
- // Now we will have to eliminate by trying all possebilities.
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsPRUint8);
- return 'PRUint8';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsPRUint16);
- return 'PRUint16';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsPRInt16);
- return 'PRInt16';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsPRInt32);
- return 'PRInt32';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsPRBool);
- return 'PRBool';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsChar);
- return 'Char';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsCString);
- return 'CString';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsFloat);
- return 'Float';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsDouble);
- return 'Double';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsPRTime);
- return 'PRTime';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsIInputStream);
- return 'InputStream';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsISupportsArray);
- return 'Array';
- } catch(e) {}
-
- try {
- obj.QueryInterface(Components.interfaces.nsIDictionary);
- return 'Dictionary';
- } catch(e) {}
-
- // Not a supported type
- return 'Unknown';
- },
-
- // Response parsing state
- _valueStack: [],
- _currValue: null,
- _cdata: null,
-
- parse: function(doc) {
- var node = doc.firstChild;
- var result;
- if (node.nodeType == DOMNode.TEXT_NODE)
- node = node.nextSibling;
- if ((node.nodeType != DOMNode.ELEMENT_NODE) ||
- (node.nodeName != 'methodResponse')) {
- throw Components.Exception('Expecting a methodResponse', null, null,
- doc);
- }
- node = node.firstChild;
- if (node.nodeType == DOMNode.TEXT_NODE)
- node = node.nextSibling;
- if (node.nodeType != DOMNode.ELEMENT_NODE)
- throw Components.Exception('Expecting a params or fault', null,
- null, doc);
- if (node.nodeName == 'params') {
- node = node.firstChild;
- if (node.nodeType == DOMNode.TEXT_NODE)
- node = node.nextSibling;
- if ((node.nodeType != DOMNode.ELEMENT_NODE) ||
- (node.nodeName != 'param')) {
- throw Components.Exception('Expecting a param', null, null,
- doc);
- }
- result = this.parseValue(node.firstChild);
- } else if (node.nodeName == 'fault') {
- this._foundFault = true;
- result = this.parseFault(node.firstChild);
- } else {
- throw Components.Exception('Expecting a params or fault', null,
- null, doc);
- }
- debug('Parse finished');
- return result;
- },
-
- parseValue: function(node) {
- var cValue = new Value();
- if (node && (node.nodeType == DOMNode.TEXT_NODE))
- node = node.nextSibling;
- if (!node || (node.nodeType != DOMNode.ELEMENT_NODE) ||
- (node.nodeName != 'value')) {
- throw Components.Exception('Expecting a value', null, null, node);
- }
- node = node.firstChild;
- if (!node)
- return cValue;
- if (node.nodeType == DOMNode.TEXT_NODE){
- if (!node.nextSibling) {
- cValue.value = node.nodeValue;
- return cValue;
- } else {
- node = node.nextSibling;
- }
- }
- if (node.nodeType != DOMNode.ELEMENT_NODE)
- throw Components.Exception('Expecting a value type', null, null,
- node);
- switch (node.nodeName) {
- case 'string':
- cValue.value = this.parseString(node.firstChild);
- break;
- case 'i4':
- case 'int':
- cValue.type = this.INT;
- cValue.value = this.parseString(node.firstChild);
- break;
- case 'boolean':
- cValue.type = this.BOOLEAN;
- cValue.value = this.parseString(node.firstChild);
- break;
- case 'double':
- cValue.type = this.DOUBLE;
- cValue.value = this.parseString(node.firstChild);
- break;
- case 'dateTime.iso8601':
- cValue.type = this.DATETIME;
- cValue.value = this.parseString(node.firstChild);
- break;
- case 'base64':
- cValue.type = this.BASE64;
- cValue.value = this.parseString(node.firstChild);
- break;
- case 'struct':
- cValue.type = this.STRUCT;
- this.parseStruct(cValue, node.firstChild);
- break;
- case 'array':
- cValue.type = this.ARRAY;
- this.parseArray(cValue, node.firstChild);
- break;
- default:
- throw Components.Exception('Expecting a value type', null, null,
- node);
- }
- return cValue;
- },
-
- parseString: function(node) {
- value = '';
- while (node) {
- if (node.nodeType != DOMNode.TEXT_NODE)
- throw Components.Exception('Expecting a text node', null, null,
- node);
- value += node.nodeValue;
- node = node.nextSibling;
- }
- return value;
- },
-
- parseStruct: function(struct, node) {
- while (node) {
- if (node.nodeType == DOMNode.TEXT_NODE)
- node = node.nextSibling;
- if (!node)
- return;
- if ((node.nodeType != DOMNode.ELEMENT_NODE) ||
- (node.nodeName != 'member')) {
- throw Components.Exception('Expecting a member', null, null,
- node);
- }
- this.parseMember(struct, node.firstChild);
- node = node.nextSibling;
- }
- },
-
- parseMember: function(struct, node) {
- var cValue;
- if (node.nodeType == DOMNode.TEXT_NODE)
- node = node.nextSibling;
- if (!node || (node.nodeType != DOMNode.ELEMENT_NODE) ||
- (node.nodeName != 'name')) {
- throw Components.Exception('Expecting a name', null, null, node);
- }
- struct.name = this.parseString(node.firstChild);
- cValue = this.parseValue(node.nextSibling);
- struct.appendValue(cValue.value);
- },
-
- parseArray: function(array, node) {
- if (node.nodeType == DOMNode.TEXT_NODE)
- node = node.nextSibling;
- if (!node || (node.nodeType != DOMNode.ELEMENT_NODE) ||
- (node.nodeName != 'data')) {
- throw Components.Exception('Expecting array data', null, null, node);
- }
- for (node = node.firstChild; node; node = node.nextSibling) {
- if (node.nodeType == DOMNode.TEXT_NODE)
- continue;
- array.appendValue(this.parseValue(node).value);
- }
- },
-
- parseFault: function(node) {
- var fault = createInstance(XMLRPCFAULT_CONTRACTID, 'nsIXmlRpcFault');
- var cValue = this.parseValue(node);
- if ((cValue.type != this.STRUCT) ||
- (!cValue.value.hasKey('faultCode')) ||
- (!cValue.value.hasKey('faultString'))) {
- throw Components.Exception('Invalid fault', null, null, node);
- }
- fault.init(cValue.value.getValue('faultCode').data,
- cValue.value.getValue('faultString').data);
- return fault;
- }
- };
-
- /* The XMLWriter class constructor */
- function XMLWriter(encoding) {
- if (!encoding)
- encoding = "UTF-8";
- this.data = '<?xml version="1.0" encoding="' + encoding + '"?>';
- }
-
- /* The XMLWriter class def */
- XMLWriter.prototype = {
- data: '',
-
- startElement: function(element) {
- this.data += '<' + element + '>';
- },
-
- endElement: function(element) {
- this.data += '</' + element + '>';
- },
-
- write: function(text) {
- for (var i = 0; i < text.length; i++) {
- var c = text[i];
- switch (c) {
- case '<':
- this.data += '<';
- break;
- case '&':
- this.data += '&';
- break;
- default:
- this.data += c;
- }
- }
- },
-
- markup: function(text) { this.data += text }
- };
-
- /* The Value class contructor */
- function Value() { this.type = this.STRING; };
-
- /* The Value class def */
- Value.prototype = {
- INT: nsXmlRpcClient.prototype.INT,
- BOOLEAN: nsXmlRpcClient.prototype.BOOLEAN,
- STRING: nsXmlRpcClient.prototype.STRING,
- DOUBLE: nsXmlRpcClient.prototype.DOUBLE,
- DATETIME: nsXmlRpcClient.prototype.DATETIME,
- ARRAY: nsXmlRpcClient.prototype.ARRAY,
- STRUCT: nsXmlRpcClient.prototype.STRUCT,
- BASE64: nsXmlRpcClient.prototype.BASE64,
-
- _createType: nsXmlRpcClient.prototype.createType,
-
- name: null,
-
- _value: null,
- get value() { return this._value; },
- set value(val) {
- // accepts [0-9]+ or x[0-9a-fA-F]+ and returns the character.
- function entityTrans(substr, code) {
- return String.fromCharCode("0" + code);
- }
-
- switch (this.type) {
- case this.STRING:
- val = val.replace(/([0-9]+);/g, entityTrans);
- val = val.replace(/(x[0-9a-fA-F]+);/g, entityTrans);
- val = val.replace(/</g, '<');
- val = val.replace(/>/g, '>');
- val = val.replace(/&/g, '&');
- this._value.data = val;
- break;
-
- case this.BOOLEAN:
- this._value.data = (val == 1);
- break;
-
- case this.DATETIME:
- this._value.data = Date.UTC(val.slice(0, 4),
- val.slice(4, 6) - 1, val.slice(6, 8), val.slice(9, 11),
- val.slice(12, 14), val.slice(15));
- break;
-
- case this.BASE64:
- this._value.data = base64ToString(val);
- break;
-
- default:
- this._value.data = val;
- }
- },
-
- _type: null,
- get type() { return this._type; },
- set type(type) {
- this._type = type;
- if (type == this.BASE64)
- this._value = this._createType(this.STRING, {});
- else this._value = this._createType(type, {});
- },
-
- appendValue: function(val) {
- switch (this.type) {
- case this.ARRAY:
- this.value.AppendElement(val);
- break;
-
- case this.STRUCT:
- this.value.setValue(this.name, val);
- break;
- }
- }
- };
-
- /*
- * Objects
- */
-
- /* nsXmlRpcClient Module (for XPCOM registration) */
- var nsXmlRpcClientModule = {
- registerSelf: function(compMgr, fileSpec, location, type) {
- compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
-
- compMgr.registerFactoryLocation(XMLRPCCLIENT_CID,
- 'XML-RPC Client JS component',
- XMLRPCCLIENT_CONTRACTID,
- fileSpec,
- location,
- type);
- compMgr.registerFactoryLocation(XMLRPCFAULT_CID,
- 'XML-RPC Fault JS component',
- XMLRPCFAULT_CONTRACTID,
- fileSpec,
- location,
- type);
- },
-
- getClassObject: function(compMgr, cid, iid) {
- if (!cid.equals(XMLRPCCLIENT_CID) && !cid.equals(XMLRPCFAULT_CID))
- throw Components.results.NS_ERROR_NO_INTERFACE;
-
- if (!iid.equals(Components.interfaces.nsIFactory))
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-
- if (cid.equals(XMLRPCCLIENT_CID))
- return nsXmlRpcClientFactory
- else return nsXmlRpcFaultFactory;
- },
-
- canUnload: function(compMgr) { return true; }
- };
-
- /* nsXmlRpcClient Class Factory */
- var nsXmlRpcClientFactory = {
- createInstance: function(outer, iid) {
- if (outer != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
-
- if (!iid.equals(XMLRPCCLIENT_IID) &&
- !iid.equals(Components.interfaces.nsISupports))
- throw Components.results.NS_ERROR_INVALID_ARG;
-
- return new nsXmlRpcClient();
- }
- }
-
- /* nsXmlRpcFault Class Factory */
- var nsXmlRpcFaultFactory = {
- createInstance: function(outer, iid) {
- if (outer != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
-
- if (!iid.equals(XMLRPCFAULT_IID) &&
- !iid.equals(Components.interfaces.nsISupports))
- throw Components.results.NS_ERROR_INVALID_ARG;
-
- return new nsXmlRpcFault();
- }
- }
-
- /*
- * Functions
- */
-
- /* module initialisation */
- function NSGetModule(comMgr, fileSpec) { return nsXmlRpcClientModule; }
-
- /* Create an instance of the given ContractID, with given interface */
- function createInstance(contractId, intf) {
- return Components.classes[contractId]
- .createInstance(Components.interfaces[intf]);
- }
-
- /* Get a pointer to a service indicated by the ContractID, with given interface */
- function getService(contractId, intf) {
- return Components.classes[contractId]
- .getService(Components.interfaces[intf]);
- }
-
- /* Convert an inputstream to a scriptable inputstream */
- function toScriptableStream(input) {
- var SIStream = Components.Constructor(
- '@mozilla.org/scriptableinputstream;1',
- 'nsIScriptableInputStream', 'init');
- return new SIStream(input);
- }
-
- /* format a Date object into a iso8601 datetime string, UTC time */
- function iso8601Format(date) {
- var datetime = date.getUTCFullYear();
- var month = String(date.getUTCMonth() + 1);
- datetime += (month.length == 1 ? '0' + month : month);
- var day = date.getUTCDate();
- datetime += (day < 10 ? '0' + day : day);
-
- datetime += 'T';
-
- var hour = date.getUTCHours();
- datetime += (hour < 10 ? '0' + hour : hour) + ':';
- var minutes = date.getUTCMinutes();
- datetime += (minutes < 10 ? '0' + minutes : minutes) + ':';
- var seconds = date.getUTCSeconds();
- datetime += (seconds < 10 ? '0' + seconds : seconds);
-
- return datetime;
- }
-
- /* Convert a stream to Base64, writing it away to a string writer */
- const BASE64CHUNK = 255; // Has to be dividable by 3!!
- function streamToBase64(stream, writer) {
- while (stream.available()) {
- var data = [];
- while (data.length < BASE64CHUNK && stream.available()) {
- var d = stream.read(1).charCodeAt(0);
- // reading a 0 results in NaN, compensate.
- data = data.concat(isNaN(d) ? 0 : d);
- }
- writer.write(toBase64(data));
- }
- }
-
- /* Convert data (an array of integers) to a Base64 string. */
- const toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +
- '0123456789+/';
- const base64Pad = '=';
- function toBase64(data) {
- var result = '';
- var length = data.length;
- var i;
- // Convert every three bytes to 4 ascii characters.
- for (i = 0; i < (length - 2); i += 3) {
- result += toBase64Table[data[i] >> 2];
- result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
- result += toBase64Table[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)];
- result += toBase64Table[data[i+2] & 0x3f];
- }
-
- // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
- if (length%3) {
- i = length - (length%3);
- result += toBase64Table[data[i] >> 2];
- if ((length%3) == 2) {
- result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
- result += toBase64Table[(data[i+1] & 0x0f) << 2];
- result += base64Pad;
- } else {
- result += toBase64Table[(data[i] & 0x03) << 4];
- result += base64Pad + base64Pad;
- }
- }
-
- return result;
- }
-
- /* Convert Base64 data to a string */
- const toBinaryTable = [
- -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
- 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
- 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
- -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
- 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
- ];
- function base64ToString(data) {
- var result = '';
- var leftbits = 0; // number of bits decoded, but yet to be appended
- var leftdata = 0; // bits decoded, but yet to be appended
-
- // Convert one by one.
- for (var i = 0; i < data.length; i++) {
- var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
- var padding = (data[i] == base64Pad);
- // Skip illegal characters and whitespace
- if (c == -1) continue;
-
- // Collect data into leftdata, update bitcount
- leftdata = (leftdata << 6) | c;
- leftbits += 6;
-
- // If we have 8 or more bits, append 8 bits to the result
- if (leftbits >= 8) {
- leftbits -= 8;
- // Append if not padding.
- if (!padding)
- result += String.fromCharCode((leftdata >> leftbits) & 0xff);
- leftdata &= (1 << leftbits) - 1;
- }
- }
-
- // If there are any bits left, the base64 string was corrupted
- if (leftbits)
- throw Components.Exception('Corrupted base64 string');
-
- return result;
- }
-
- if (DEBUG) debug = function(msg) {
- dump(' -- XML-RPC client -- : ' + msg + '\n');
- };
- else debug = function() {}
-
- // vim:sw=4:sr:sta:et:sts:
-